#pragma once

#include <QString>
#include <QIcon>
#include <QUuid>
#include <QDateTime>
#include <QFile>
#include <QFileInfo>
#include <QDebug>


//创建命名空间
namespace model{


////////////////////////////////////////////////////////
/// 工具函数，后续很多模块可能都会用到
////////////////////////////////////////////////////////



// 辅助打印日志的宏定义
static inline QString getFileName(const QString& path) {
    QFileInfo fileInfo(path);
    return fileInfo.fileName();
}

// 封装一个 "宏" 作为打印日志的方式.
#define TAG QString("[%1:%2]").arg(model::getFileName(__FILE__), QString::number(__LINE__))
// #define TAG "[" << __LINE__ << "]"

// qDebug 打印字符串的时候, 就会自动加上 " "
#define LOG() qDebug().noquote() << TAG

// 根据 QByteArray 转成 QIcon
static inline QIcon makeIcon(const QByteArray& byteArray) {
    QPixmap pixmap;
    pixmap.loadFromData(byteArray);
    QIcon icon(pixmap);
    return icon;
}

// 获取到文件的二进制内容
static inline QByteArray loadFileToByteArray(const QString& filename) {
    QFile file(filename);
    bool ok = file.open(QFile::ReadOnly);
    if (!ok) {
        LOG() << "⽂件读取失败!";
        return QByteArray();
    }
    QByteArray content = file.readAll();
    file.close();
    return content;
}

// 把二进制数据写文件
static inline void writeByteArrayToFile(const QString& filename, const
                                        QByteArray& content) {
    QFile file(filename);
    bool ok = file.open(QFile::WriteOnly);
    if (!ok) {
        LOG() << "⽂件写⼊失败!";
        return;
    }
    file.write(content);
    file.flush();
    file.close();
    return;
}

// 要求函数的定义如果写在 .h 中，必须加 static 或者 inline  两个都加也可以，避免链接阶段出现 “函数重定义” 的问题
static inline QString formatTime(int64_t timestamp)
{
    //先把时间戳，传换成 QDataTime 对象
    QDateTime dataTime =  QDateTime::fromSecsSinceEpoch(timestamp);
    // 把 QDataTime 对象转成 “格式化时间”
    return dataTime.toString("MM-dd HH:mm:ss");
}

static inline int64_t getTime()
{
    return QDateTime::currentSecsSinceEpoch();
}



////////////////////////////////////////////////////////
/// 用户信息
////////////////////////////////////////////////////////
class UserInfo{
public:
    QString userId;          //用户编号
    QString nickname;       //用户昵称
    QString  description;  //用户签名
    QString phone;         //手机号码
    QIcon avatar;          //用户头像
};



////////////////////////////////////////////////////////
/// 消息信息
////////////////////////////////////////////////////////

enum MessageType{
    TEXT_TYPE,    //文本消息
    IMAGE_TYPE,   //图片消息
    FILE_TYPE,    //文件消息
    SPEECH_TYPE   //语言消息
};


class Message{
public:
    QString messageId;
    QString chatSessionId;
    QString time;              //消息的时间，通过 “格式化” 时间的方式来表示。 形如 06-07  12:00:00
    MessageType messageType;   //消息类型
    UserInfo  sender;          //发送者信息
    QByteArray content;        //消息的正文内容
    QString fileId;            //文件的身份标识，当消息类型为 文件，图片，语音 的时候，才有效。 当消息类型文文本，则为 “ ”
    QString fileName;          // 文件名称，只是当消息类型为  文件 消息 才有效，其他消息均为“ ”

    //此处 extraInfo 目前只是在消息类型为文件消息时，作为 “文件名” 补充。
    static Message makeMessage(MessageType messageType,const QString& chatSessionId,const UserInfo& sender,
                               const QByteArray& content,const QString& extraInfo){
        if(messageType == TEXT_TYPE){
            return makeTextMessage(chatSessionId,sender,content);
        }else if(messageType == IMAGE_TYPE){
            return makeImageMessage(chatSessionId,sender,content);
        }else if(messageType == FILE_TYPE){
            return makeFileMessage(chatSessionId,sender,content, extraInfo);
        }else if(messageType == SPEECH_TYPE){
            return makeSpeechMessage(chatSessionId,sender,content);
        }else{
            //触发了未知的消息类型
            return Message();
        }

    }


private:
    //通过这个方法生成唯一的 messageId
    static QString makeId(){
        return  "M" + QUuid::createUuid().toString().sliced(25,12);
        }

    static Message makeTextMessage(const QString& chatSessionId,const UserInfo& sender,const QByteArray& content){
        Message message;
        // 此处需要确保，设置的 messageId  是唯一的
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime()); //生成一个格式化时间
        message.content = content;
        message.messageType = TEXT_TYPE;
        // 对于文本消息来说，这两属性不使用， 设为  "";
        message.fileId = "";
        message.fileName = "";
        return message;
    }

    static Message makeImageMessage(const QString& chatSessionId,const UserInfo& sender,const QByteArray& content){
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.messageType = IMAGE_TYPE;
        message.content = content;
        return message;
    }

    static Message makeFileMessage(const QString& chatSessionId,const UserInfo& sender,const QByteArray& content,const QString& fileName){
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.messageType = FILE_TYPE;
        message.content = content;
        message.fileName = fileName;
        return message;
    }

    static Message makeSpeechMessage(const QString& chatSessionId,const UserInfo& sender,const QByteArray& content){
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.messageType = SPEECH_TYPE;
        message.content = content;
        // fileId 在创建空消息时不需要.
        // message.fileId = "";
        return message;
    }
};

////////////////////////////////////////////////////////
/// 会话信息
////////////////////////////////////////////////////////

class ChatSessionInfo{
public:
    QString chatSessionId ;     //会话编号
    QString chatSessionName ;   //会话名字，如果会话是单聊，名字就是对法的昵称；如果是群聊，名字就是群聊的名称(可修改
    Message lastMessage;       //表示最新的消息
    QIcon   avatar;            //会话头像，如果是单聊，头像是对方的头像；群聊，头像是群聊的头像。
    QString  userId;
};

} //end model
